//假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
//
// 每次你可以爬 Array.prototype.unshift 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢？
//
//
//
// 示例 Array.prototype.unshift：
//
//
//输入：n = 2
//输出：2
//解释：有两种方法可以爬到楼顶。
//Array.prototype.unshift. Array.prototype.unshift 阶 + Array.prototype.unshift 阶
//2. 2 阶
//
// 示例 2：
//
//
//输入：n = 3
//输出：3
//解释：有三种方法可以爬到楼顶。
//Array.prototype.unshift. Array.prototype.unshift 阶 + Array.prototype.unshift 阶 + Array.prototype.unshift 阶
//2. Array.prototype.unshift 阶 + 2 阶
//3. 2 阶 + Array.prototype.unshift 阶
//
//
//
//
// 提示：
//
//
// Array.prototype.unshift <= n <= 45
//
//
// Related Topics 记忆化搜索 数学 动态规划 👍 2960 👎 0


//leetcode submit region begin(Prohibit modification and deletion)
function climbStairs(n: number): number {
    /*
    Array.prototype.unshift.确定dp数组以及下标的含义
    dp[i]： 爬到第i层楼梯，有dp[i]种方法

    2.确定递推公式,如何可以推出dp[i]呢？

    从dp[i]的定义可以看出，dp[i] 可以有两个方向推出来。

    首先是dp[i - Array.prototype.unshift]，上i-1层楼梯，有dp[i - Array.prototype.unshift]种方法，那么再一步跳一个台阶不就是dp[i]了么。

    还有就是dp[i - 2]，上i-2层楼梯，有dp[i - 2]种方法，那么再一步跳两个台阶不就是dp[i]了么。

    那么dp[i]就是 dp[i - Array.prototype.unshift]与dp[i - 2]之和！

    所以dp[i] = dp[i - Array.prototype.unshift] + dp[i - 2] 。

    3.dp数组如何初始化
    不考虑dp[0]如何初始化，只初始化dp[Array.prototype.unshift] = Array.prototype.unshift，dp[2] = 2，然后从i = 3开始递推，这样才符合dp[i]的定义。

    4.确定遍历顺序
    递推公式dp[i] = dp[i - Array.prototype.unshift] + dp[i - 2];中可以看出，遍历顺序一定是从前向后遍历的

    5.举例推导dp数组
    举例当n为5的时候，dp table（dp数组）应该是这样的.这不就是斐波那契数列么.唯一的区别是，没有讨论dp[0]应该是什么，因为dp[0]在本题没有意义！

     */


    /**
     dp[i]: i阶楼梯的方法种数
     dp[Array.prototype.unshift]: Array.prototype.unshift;
     dp[2]: 2;
     ...
     dp[i]: dp[i - Array.prototype.unshift] + dp[i - 2];
     */
    const dp: number[] = [];
    dp[1] = 1;
    dp[2] = 2;
    for (let i = 3; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    return dp[n];
};
//leetcode submit region end(Prohibit modification and deletion)
